package com.hghivln.erpwarehouse.system.controller;


import cn.hutool.captcha.CaptchaUtil;
import cn.hutool.captcha.ShearCaptcha;
import com.hghivln.erpwarehouse.system.common.lang.ActiverUser;
import com.hghivln.erpwarehouse.system.common.lang.Constant;
import com.hghivln.erpwarehouse.system.common.lang.Result;
import com.hghivln.erpwarehouse.system.entity.Loginfo;
import com.hghivln.erpwarehouse.system.entity.User;
import com.hghivln.erpwarehouse.system.service.LoginfoService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author hghivln
 * @since 2021-06-21
 */
@Controller
@RequestMapping("api/login")
public class LoginController {

    @Autowired
    private LoginfoService loginfoService;

    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 用户登录
     */
    @ResponseBody
    @RequestMapping("doLogin")
    public Result doLogin(String loginname, String password, String captcha, String keyCode, HttpServletRequest request) {
        try {
            // 根据key从redis中拿到验证码
            ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
            String code = opsForValue.get(keyCode);
            assert code != null;
            if (code.equals(captcha)) {
                Subject subject = SecurityUtils.getSubject();
                UsernamePasswordToken loginToken = new UsernamePasswordToken(loginname, password);
                subject.login(loginToken);

                // 记录登录日志
                Loginfo loginfo = new Loginfo();
                ActiverUser activerUser = (ActiverUser) subject.getPrincipal();
                User user = activerUser.getUser();
                loginfo.setLoginname(user.getLoginname() + "【" + user.getName() + "】");
                loginfo.setLogintime(new Date());
                loginfo.setLoginip(request.getRemoteAddr());
                loginfoService.save(loginfo);

                List<String> permission = activerUser.getPermission();
                HashMap<String, Object> map = new HashMap<>();
                // 得到shiro的sessionid==token
                String token = subject.getSession().getId().toString();
                map.put("permissions", permission);
                map.put("token", token);
                map.put("username", user.getName());
                return new Result(Constant.OK, "登录成功", map);
            }else {
                return Result.LOGIN_ERROR_CODE;
            }
        } catch (AuthenticationException e) {
            e.printStackTrace();
            return Result.LOGIN_ERROR_PASS;
        }
    }

    /**
     * 验证当前token是否登录
     */
    @ResponseBody
    @RequestMapping("checkLogin")
    public Result checkLogin() {
        Subject subject = SecurityUtils.getSubject();
        if (subject.isAuthenticated()) {
            return Result.LOGGED;
        } else {
            return Result.NOT_LOGGED_IN;
        }

    }

    /**
     * 生成验证码
     */
    @RequestMapping("captcha")
    public void captch(String keyCode, HttpServletResponse response) throws IOException {
        // 定义图形验证码的长、宽、验证码字符数、干扰线宽度
        ShearCaptcha captcha = CaptchaUtil.createShearCaptcha(100, 38, 4, 4);
        // 获取验证码的文字内容
        String code = captcha.getCode();
        // 以键值形式序列化后放入redis中
        ValueOperations<String, String> opsForValue = redisTemplate.opsForValue();
        opsForValue.set(keyCode, code);
        opsForValue.getOperations().expire(keyCode, 60, TimeUnit.SECONDS);
        // 图形验证码写出到流
        captcha.write(response.getOutputStream());
    }
}
